package com.zxlspace.thread;

import com.sun.org.apache.bcel.internal.generic.NEW;

/**
 * 这段代码的打印结果是，methodA…..methodC…..会很快打印出来，methodB…..会隔一段时间才打印出来，那么methodB为什么不能像methodC那样很快被调用呢？

 在启动线程1调用方法A后，接着会让线程1休眠5秒钟，这时会调用方法C，注意到方法C这里用synchronized进行加锁，这里锁的对象是str这个字符串对象。
 但是方法B则不同，是用当前对象this进行加锁，注意到方法A直接在方法上加synchronized，这个加锁的对象是什么呢？显然，这两个方法用的是一把锁。

 *由这样的结果，我们就知道这样同步方法是用什么加锁的了，由于线程1在休眠，这时锁还没释放，导致线程2只有在5秒之后才能调用方法B，由此，可知两种加锁机制用的是同一个锁对象，即当前对象。 
 另外，同步方法直接在方法上加synchronized实现加锁，同步代码块则在方法内部加锁，很明显，同步方法锁的范围比较大，而同步代码块范围要小点，一般同步的范围越大，
 性能就越差，一般需要加锁进行同步的时候，肯定是范围越小越好，这样性能更好
 *
 */
public class SynObj {

    public synchronized void methodA() {
        System.out.println("methodA.....");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void methodB(){
        synchronized (this) {
            System.out.println("methodB。。。。。");
        }
    }

    public void methodC(){
        String str = "rrr";
        synchronized (str) {
            System.out.println("methodC。。。。。");
        }
    }
}

class TestSynObj {
    public static void main(String[] args) {
        final SynObj synObj = new SynObj();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synObj.methodA();
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synObj.methodB();
            }
        });

        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                synObj.methodC();
            }
        });

        t1.start();
        t2.start();
        t3.start();

        //单例饿汉模式
        Runtime runtime = Runtime.getRuntime();
    }
}
